import * as cc from "cc";
import yyComponent from "../../Script/Common/yyComponent";
import { GlobalEnum } from "../../Script/GameSpecial/GlobalEnum";
import { EventType } from "../../Script/GameSpecial/GameEventType";
import Action3dManager, { ActionMngType, Action3d } from "../../Script/Common/Action3dManager";
import GlobalPool from "../../Script/Common/GlobalPool";
import GlobalData from "../../Script/Common/GlobalData";
import GameConfig from "../../Script/GameSpecial/GameConfig";
import MapData from "../../Script/GameSpecial/MapData";

//关卡进度分数等信息UI
const { ccclass, property } = cc._decorator;

@ccclass
export default class LevelInfoUI extends yyComponent {

    public get uiType() { return GlobalEnum.UI.levelInfo; }

    public init() {
        this.initCarIcon();
        this.initCurGold();
        this.initEndRoadTouchTip();
        this.initGoldParticleLayer();
        this.initHandAnim();
        this.initMingCi();
        this.initPartCount();
        this.initPartDropLayer();
        this.initPartParticleLayer();
        this.initProgress();
        this.initRoleIcons();
        this.initTerrainTip();

        this.onEvents();
    }
    protected onEvents() {
        // this.on(EventType.LevelEvent.resurgence, this.onResurgence, this);
        this.on(EventType.LevelEvent.updateLevelProgress, this.setProgress, this);
        this.on(EventType.LevelEvent.addGoldParticle, this.addGoldParticle, this);
        this.on(EventType.LevelEvent.playAddCarPartUIAnim, this.addPartParticle, this);
        this.on(EventType.LevelEvent.playDropCarPartUIAnim, this.addPartDropParticle, this);
        this.on(EventType.LevelEvent.updatePlayerCurPartCount, this.updateCurPartCount, this);
        this.on(EventType.LevelEvent.playerPartFull, this.onPlayerPartFull, this);
        this.on(EventType.LevelEvent.playerPartExitFull, this.onPlayerPartExitFull, this);
        this.on(EventType.LevelEvent.playerEnterTerrain, this.startTerrainTip, this);
        this.on(EventType.LevelEvent.playerExitTerrain, this.stopTerrainTip, this);
        this.on(EventType.Common.DirectorEvent.playerWin, this.hideGoldBar, this);
        this.on(EventType.LevelEvent.showHandAnim, this.showHandAnim, this);
        this.on(EventType.LevelEvent.showHandAnim, this.showProgress, this);
        this.on(EventType.LevelEvent.playerChangeCar, this.onPlayerChangeCar, this);
        this.on(EventType.LevelEvent.enemyChangeCar, this.onEnemyChangeCar, this);
        this.on(EventType.LevelEvent.showHandAnim, this.bindRoleIcons, this);
        this.on(EventType.LevelEvent.updateMingCi, this.setMingCi, this);
        this.on(EventType.LevelEvent.showEndRoadTouchTip, this.showEndRoadTouchTip, this);
        this.on(EventType.LevelEvent.hideEndRoadTouchTip, this.hideEndRoadTouchTip, this);
    }
    public reset() {
        this.resetCarIcon();
        this.resetCurGold();
        this.resetEndRoadTouchTip();
        this.resetGoldParticleLayer();
        this.resetHandAnim();
        this.resetMingCi();
        this.resetPartCount();
        this.resetPartDropLayer();
        this.resetPartParticleLayer();
        this.resetProgress();
        this.resetRoleIcons();
        this.resetTerrainTip();
    }

    public show(levelData: any) {
        this.node.active = true;
        this.reset();
        this.setData(levelData);
        this.onEvents();
        this.emit(EventType.Common.DirectorEvent.resumeLevel);
    }
    public hide() {
        this.reset();
        this.offEvents();
        this.node.active = false;
    }

    public getData() {
        return {
            lv: this.lv,
            speGold: 0,
            gold: this.curGold,
        };
    }

    protected lv: number;
    protected setData(data: any) {
        this.lv = data.lv;
        this.curLevel.string = "" + this.lv;
        this.levelProgress.width = 1;
        if (GlobalData.get(GlobalEnum.myGlobalDataType.tryMaxCar)) {
            this.setTotalPartCount(97);
            this.updateCurPartCount(97);
        }
    }

    protected convertToString(v: number): string {
        if (v < 1100) return v.toString();
        if (v < 1100000) return (v * 0.001).toFixed(1) + "K";
        return (v * 0.000001).toFixed(1) + "M";
    }

    /****************************************管理对象****************************************/
    //#region 关卡进度
    @property(cc.Node)
    protected levelProgressBg: cc.Node = null;
    @property(cc.UITransform)
    protected levelProgress: cc.UITransform = null;
    protected levelProgressTotalLength: number = 600;
    @property(cc.Label)
    protected curLevel: cc.Label = null;
    protected initProgress() {
        this.levelProgress.width = this.levelProgressTotalLength;
        this.levelProgressBg.active = false;
    }
    protected resetProgress() {
        this.levelProgressBg.active = false;
    }
    protected setProgress(r: number) {
        if (r > 1) {
            r = 1;
        }
        let w = this.levelProgressTotalLength * r;
        if (w < 1) {
            w = 1;
        }
        this.levelProgress.width = w;
    }
    protected showProgress() {
        this.levelProgressBg.active = true;
    }
    //#endregion

    //#region 角色位置标志
    @property(cc.Node)
    protected playerIcon: cc.Node = null;
    @property([cc.Node])
    protected roleIcons: cc.Node[] = [];
    protected roleIconMap: { [id: number]: { icon: cc.Node, role: yyComponent } } = null;
    protected totalRoadLen: number;
    protected initRoleIcons() {
        this.totalRoadLen = 1;
    }
    protected resetRoleIcons() {
        this.playerIcon.getComponent(cc.Sprite).spriteFrame = this.carIconImgs[0];
        this.playerIcon.setPosition(0, -60, 0);
        for (let i = 0; i < this.roleIcons.length; ++i) {
            this.roleIcons[i].getComponent(cc.Sprite).spriteFrame = this.carIconImgs[0];
            this.roleIcons[i].setPosition(0, 60, 0);
        }
        this.roleIconMap = null;
    }
    protected bindRoleIcons() {
        let roles = GlobalData.get(GlobalEnum.myGlobalDataType.enemies);
        this.roleIconMap = {};
        for (let i = 0; i < roles.length; ++i) {
            this.roleIconMap[roles[i].Id] = {
                icon: this.roleIcons[i],
                role: roles[i],
            };
        }
        this.totalRoadLen = GameConfig.GameRule.startLinePosZ + MapData.getTotalLen();
    }
    protected updateRoleIcons() {
        if (!this.roleIconMap) {
            return;
        }
        for (let key in this.roleIconMap) {
            let z = this.roleIconMap[key].role.z;
            let r = (GameConfig.GameRule.startLinePosZ - z) / this.totalRoadLen;
            if (r > 1) {
                r = 1;
            }
            this.roleIconMap[key].icon.setPosition(this.levelProgressTotalLength * r, 60, 0);
        }
        let r = (GameConfig.GameRule.startLinePosZ - GlobalData.get(GlobalEnum.myGlobalDataType.player).z) / this.totalRoadLen;
        if (r)
            this.playerIcon.setPosition(this.levelProgressTotalLength * r, -60, 0);
    }
    //#endregion

    //#region 金币
    @property(cc.Label)
    protected curGoldLabel: cc.Label = null;
    protected curGold: number = 0;
    protected _goldTargetPos: cc.Vec3;
    protected goldAddElapsed: number = 0;
    protected goldAddDuration: number = 0.1;

    protected get goldTargetPos() {
        if (!this._goldTargetPos) {
            this._goldTargetPos = this.curGoldLabel.getComponent(cc.UITransform).convertToWorldSpaceAR(cc.v3());
            this.node.getComponent(cc.UITransform).convertToNodeSpaceAR(this._goldTargetPos, this._goldTargetPos);
        }
        return this._goldTargetPos;
    }
    protected initCurGold() {
        this.curGold = 0;
        this.curGoldLabel.string = this.curGold.toString();
        this.goldAddElapsed = this.goldAddDuration + 1;
    }
    protected resetCurGold() {
        this.curGold = 0;
        this.curGoldLabel.string = this.curGold.toString();
        this.goldAddElapsed = this.goldAddDuration + 1;
        this.curGoldLabel.node.parent.active = true;
        this.curGoldLabel.node.setScale(1, 1, 1);
    }
    protected addGold(v: number = 1) {
        this.curGold += v;
        this.curGoldLabel.string = this.curGold.toString();
        this.goldAddElapsed = 0;
    }
    protected hideGoldBar() {
        this.curGoldLabel.node.parent.active = false;
    }
    protected updateGold(g) {
        this.curGold = g;
        this.curGoldLabel.string = this.curGold.toString();
        this.goldAddElapsed = 0;
    }
    protected updateGoldLabel(dt: number) {
        if (this.goldAddElapsed > this.goldAddDuration) { return; }
        this.goldAddElapsed += dt;
        let r = 1 - this.goldAddElapsed / this.goldAddDuration;
        if (r < 0) r = 0;
        let s = 1 + 1 * r;
        this.curGoldLabel.node.setScale(s, s, s);
    }
    //#endregion

    //#region 金币动画层
    @property(cc.Node)
    protected goldParticleLayer: cc.Node = null;
    @property(cc.Prefab)
    protected goldParticle: cc.Prefab = null;
    protected initGoldParticleLayer() {
        GlobalPool.createPool(this.goldParticle.data.name, this.goldParticle);
    }
    protected resetGoldParticleLayer() {
        GlobalPool.putAllChildren(this.goldParticleLayer, true);
    }
    protected addGoldParticle(data: { p: cc.Vec3, gold: number }) {
        let node = GlobalPool.get(this.goldParticle.data.name);
        this.goldParticleLayer.addChild(node);
        node.setPosition(data.p);
        let s = 1;
        node.setScale(s, s);
        let d = 0.5;
        let move = Action3dManager.moveTo(d, this.goldTargetPos.x, this.goldTargetPos.y, 0);
        // move.easing(Action3dManager.easeIn(3));
        s = 0.5;
        let scale = Action3dManager.scaleTo(d, s, s, 1);
        // scale.easing(Action3dManager.easeIn(2));
        let spawn = Action3dManager.spawn(move, scale);
        let cb = Action3dManager.callFun(this.onGoldParticleAnimFinish, this, { node: node, gold: data.gold });
        let seq = Action3dManager.sequence(spawn, cb);
        Action3dManager.getMng(ActionMngType.UI).runAction(node, seq);
    }
    protected onGoldParticleAnimFinish(data: { node: cc.Node, gold: number }) {
        this.updateGold(data.gold);
        GlobalPool.put(data.node);
    }
    //#endregion

    //#region 手指提示动画
    @property(cc.Node)
    protected handLoop: cc.Node = null;
    @property(cc.Animation)
    protected handAnim: cc.Animation = null;
    protected initHandAnim() {
        this.hideHandAnim();
    }
    protected resetHandAnim() {
        this.hideHandAnim();
    }
    protected showHandAnim() {
        this.once(EventType.LevelEvent.startJoy, this.hideHandAnim, this);
        this.handLoop.active = true;
        this.handAnim.play();
    }
    protected hideHandAnim() {
        this.handAnim.stop();
        this.handLoop.active = false;
    }
    //#endregion

    //#region 车辆类型标志
    @property(cc.Sprite)
    protected carIcon: cc.Sprite = null;
    @property([cc.SpriteFrame])
    protected carIconImgs: cc.SpriteFrame[] = [];
    protected initCarIcon() {
        this.carIcon.spriteFrame = this.carIconImgs[0];
    }
    protected resetCarIcon() {
        this.carIcon.spriteFrame = this.carIconImgs[0];
    }
    protected setCarIcon(type: number) {
        this.carIcon.spriteFrame = this.carIconImgs[type - 1];
    }
    protected playCarIconAnim() {
        let node = this.carIcon.node;
        let w = node.getComponent(cc.UITransform).width;
        node.setPosition(this.node.getComponent(cc.UITransform).width * 0.5 + w * 0.5, node.position.y, 0);
        let move = Action3dManager.moveBy(0.5, -w, 0, 0);
        move.easing(Action3dManager.easeSinIn());
        Action3dManager.getMng(ActionMngType.UI).runAction(node, move);
    }
    //#endregion

    //#region 车辆零件数量
    @property(cc.Label)
    protected totalPartCountLabel: cc.Label = null;
    protected totalPartCount: number = 0;
    @property(cc.Label)
    protected curPartCountLabel: cc.Label = null;
    protected curPartCount: number = 0;
    @property(cc.UITransform)
    protected partProgressBar: cc.UITransform = null;
    protected partProgressTotalLen: number = 245;
    protected partProgressTargetLen: number = 0;
    protected _partTargetPos: cc.Vec3;
    protected partAddElapsed: number = 0;
    protected partAddDuration: number = 0.1;
    protected get partTargetPos() {
        if (!this._partTargetPos) {
            this._partTargetPos = this.curPartCountLabel.getComponent(cc.UITransform).convertToWorldSpaceAR(cc.v3());
            this.node.getComponent(cc.UITransform).convertToNodeSpaceAR(this._partTargetPos, this._partTargetPos);
        }
        return this._partTargetPos;
    }
    protected initPartCount() {
        this.partAddElapsed = this.partAddDuration + 1;
        this.curPartCount = 0;
        this.totalPartCount = 12;
        this.curPartCountLabel.string = "0/";
        this.totalPartCountLabel.string = this.totalPartCount.toString();
        this.partProgressBar.width = 1;
        this.partProgressTargetLen = 0;
    }
    protected resetPartCount() {
        this.partAddElapsed = this.partAddDuration + 1;
        this.curPartCountLabel.node.setScale(1, 1, 1);
        this.curPartCount = 0;
        this.totalPartCount = 12;
        this.curPartCountLabel.string = "0/";
        this.totalPartCountLabel.string = this.totalPartCount.toString();
        this.partProgressBar.width = 1;
        this.partProgressTargetLen = 0;
    }
    protected setTotalPartCount(c: number) {
        this.totalPartCount = c;
        this.totalPartCountLabel.string = c.toString();
        this.partProgressTargetLen = this.partProgressTotalLen * this.curPartCount / this.totalPartCount;
    }
    protected updateCurPartCount(c: number) {
        if (c > this.totalPartCount) {
            c = this.totalPartCount;
        } else if (c < 0) {
            c = 0;
        }
        this.curPartCount = c;
        this.curPartCountLabel.string = c + "/";
        this.partAddElapsed = 0;
        this.partProgressTargetLen = this.partProgressTotalLen * this.curPartCount / this.totalPartCount;
    }
    protected updatePartLabel(dt: number) {
        if (this.partProgressTargetLen <= 1) {
            this.partProgressBar.width = 1;
        } else {
            let w = this.partProgressTargetLen - this.partProgressBar.width;
            if (w <= 0) {
                this.partProgressBar.width = this.partProgressTargetLen;
            } else {
                w *= dt;
                this.partProgressBar.width = this.partProgressBar.width + w;
            }
        }
        if (this.partAddElapsed > this.partAddDuration) { return; }
        this.partAddElapsed += dt;
        let r = 1 - this.partAddElapsed / this.partAddDuration;
        if (r < 0) r = 0;
        let s = 1 + 1 * r;
        this.curPartCountLabel.node.setScale(s, s, s);
    }
    //#endregion

    //#region 车辆收集零件提示动画
    @property(cc.Node)
    protected partParticleLayer: cc.Node = null;
    @property(cc.Prefab)
    protected partParticle: cc.Prefab = null;
    protected initPartParticleLayer() {
        GlobalPool.createPool(this.partParticle.data.name, this.partParticle);
    }
    protected resetPartParticleLayer() {
        GlobalPool.putAllChildren(this.partParticleLayer, true);
    }
    protected addPartParticle(data: { p: cc.Vec3, partCount: number, addCount: number }) {
        let node = GlobalPool.get(this.partParticle.data.name);
        node.children[0].getComponent(cc.Label).string = "+" + data.addCount;
        this.partParticleLayer.addChild(node);
        node.setPosition(data.p.x + 50, data.p.y + 100, 0);
        let s = 0;
        node.setScale(s, s, s);
        let d = 0.4;
        s = 1;
        let scale0 = Action3dManager.scaleTo(d, s, s, s);
        scale0.easing(Action3dManager.easeOut(2));
        d = 0.5;
        let move = Action3dManager.moveTo(d, this.partTargetPos.x, this.partTargetPos.y, 0);
        // move.easing(Action3dManager.easeIn(3));
        s = 0.5;
        let scale = Action3dManager.scaleTo(d, s, s, 1);
        // scale.easing(Action3dManager.easeIn(2));
        let spawn = Action3dManager.spawn(move, scale);
        let cb = Action3dManager.callFun(this.onPartParticleAnimFinish, this, { node: node, partCount: data.partCount });
        let seq = Action3dManager.sequence(scale0, spawn, cb);
        Action3dManager.getMng(ActionMngType.UI).runAction(node, seq);
    }
    protected onPartParticleAnimFinish(data: { node: cc.Node, partCount: number }) {
        this.updateCurPartCount(data.partCount);
        GlobalPool.put(data.node);
    }
    //#endregion

    //#region 车辆掉落零件提示动画
    @property(cc.Node)
    protected partDorpLayer: cc.Node = null;
    @property(cc.Prefab)
    protected partDropParticle: cc.Prefab = null;
    protected initPartDropLayer() {
        GlobalPool.createPool(this.partDropParticle.data.name, this.partDropParticle);
    }
    protected resetPartDropLayer() {
        GlobalPool.putAllChildren(this.partDorpLayer, true);
    }
    protected addPartDropParticle(data: { p: cc.Vec3, partCount: number, subCount: number }) {
        this.updateCurPartCount(data.partCount);
        let node = GlobalPool.get(this.partDropParticle.data.name);
        node.children[0].getComponent(cc.Label).string = "-" + data.subCount;
        this.partDorpLayer.addChild(node);
        node.setPosition(data.p.x + 50, data.p.y - 150, 0);
        let s = 0;
        node.setScale(s, s, s);
        let d = 0.5;
        s = 1;
        let scale0 = Action3dManager.scaleTo(d, s, s, s);
        scale0.easing(Action3dManager.easeElasticOut());
        d = 0.1;
        let delay = Action3dManager.delay(d);
        let cb = Action3dManager.callFun(this.onDropParticleAnimFinish, this, { node: node, partCount: data.partCount });
        let seq = Action3dManager.sequence(scale0, delay, cb);
        Action3dManager.getMng(ActionMngType.UI).runAction(node, seq);
    }
    protected onDropParticleAnimFinish(data: { node: cc.Node }) {
        GlobalPool.put(data.node);
    }
    //#endregion

    //#region 恶劣地形提示
    @property(cc.Node)
    protected terrainTip: cc.Node = null;
    protected terrainAction: Action3d = null;
    protected onBadTerrain: boolean = false;
    protected initTerrainTip() {
        this.terrainTip.active = false;

        let cb = Action3dManager.callFun(this.terrainTipVibrate, this);
        let d = 0.1;
        let s = 1.05;
        let scale0 = Action3dManager.scaleTo(d, s, s, s);
        s = 1;
        let scale1 = Action3dManager.scaleTo(d, s, s, s);
        let seq = Action3dManager.sequence(cb, scale0, scale1);
        this.terrainAction = Action3dManager.repeatForever(seq);
    }
    protected resetTerrainTip() {
        Action3dManager.getMng(ActionMngType.UI).stopAllActions(this.terrainTip);
        this.terrainTip.active = false;
    }
    protected terrainTipVibrate() {
        this.emit(EventType.Common.SDKEvent.vibrateShort);
        if (!this.onBadTerrain) {
            this.stopTerrainTip();
        }
    }
    protected startTerrainTip() {
        this.onBadTerrain = true;
        this.terrainTip.active = true;
        this.terrainTip.setScale(1, 1, 1);
        Action3dManager.getMng(ActionMngType.UI).runAction(this.terrainTip, this.terrainAction);
    }
    protected stopTerrainTip() {
        Action3dManager.getMng(ActionMngType.UI).stopAllActions(this.terrainTip);
        this.terrainTip.active = false;
        this.onBadTerrain = false;
    }
    //#endregion

    //#region 名次
    @property(cc.Label)
    protected mingCi: cc.Label = null;
    protected curMingCi: number = 4;
    protected initMingCi() {
        this.mingCi.string = "4";
        this.curMingCi = 4;
    }
    protected resetMingCi() {
        this.mingCi.string = "4";
        this.curMingCi = 4;
    }
    protected setMingCi(c) {
        if (this.curPartCount !== c) {
            this.curPartCount = c;
            this.mingCi.string = c.toString();
        }
    }
    //#endregion

    //#region 终点点击冲刺提示动画
    @property(cc.Node)
    protected endRoadTouchTip: cc.Node = null;
    protected initEndRoadTouchTip() {
        this.endRoadTouchTip.active = false;
    }
    protected resetEndRoadTouchTip() {
        this.endRoadTouchTip.active = false;
    }
    protected showEndRoadTouchTip() {
        this.endRoadTouchTip.active = true;
    }
    protected hideEndRoadTouchTip() {
        this.endRoadTouchTip.active = false;
    }
    //#endregion

    /****************************************按钮回调****************************************/
    /**设置按钮 */
    protected onBtnConfigSetting() {
        this.emit(EventType.Common.AudioEvent.playClickBtn);
        this.emit(EventType.Common.UIEvent.enter, GlobalEnum.UI.configSetting);
    }
    /**暂停按钮 */
    protected onBtnPause() {
        this.emit(EventType.Common.AudioEvent.playClickBtn);
        this.emit(EventType.Common.UIEvent.enter, GlobalEnum.UI.pauseLevel);
    }

    protected onPlayerChangeCar(data: { car: number, totalPartCount: number, curPartCount: number }) {
        this.playerIcon.getComponent(cc.Sprite).spriteFrame = this.carIconImgs[data.car - 1];
        this.setCarIcon(data.car);
        this.setTotalPartCount(data.totalPartCount);
        this.curPartCount = data.curPartCount;
        this.curPartCountLabel.string = data.curPartCount + "/";
        this.playCarIconAnim();
    }

    protected onPlayerPartFull() {
        this.curPartCountLabel.color = cc.color(204, 153, 61);
    }
    protected onPlayerPartExitFull() {
        this.curPartCountLabel.color = cc.color(255, 255, 255);
    }

    protected onStartJoy() {
        this.bindRoleIcons();
    }

    protected onEnemyChangeCar(data: { car: number, role: yyComponent }) {
        let id = data.role.Id;
        this.roleIconMap[id].icon.getComponent(cc.Sprite).spriteFrame = this.carIconImgs[data.car - 1];
    }

    public update(dt: number) {
        this.updateGoldLabel(dt);
        this.updatePartLabel(dt);
        this.updateRoleIcons();
    }

}
